/*
 * 重大修改，不保存复杂的uart_dev对象，取而代之的是简单的uart_base结构
 * Created on: Dec 14, 2009
 * Dec.14 要作重大修改 */
#include <devices/uart.h>
#include <avr/io.h>
#include <devices/uart_dev.h>
#define RBUF_DT uint8_t
#include <leaf/rbuf.h>
#include <leaf/errno.h>
typedef struct{
	volatile uint8_t status;
	char *wbuf; /* Write Buffer */
	volatile size_t	wcnt;  /* Write Counter */
	Mutex wo;
	Rbuf *rbuf;
	Mutex ro;
	Mutex rlock;  /* 对某一串口的读操作需要 */
	Mutex wlock;
}Uart, *pUart;

/* 通用的 空 Usart结构体内变量的初始化 */
#define USART_INIT_VARS     \
		.wbuf = NULL,       \
		.wcnt = 0,          \
		.rbuf = NULL,       \
		.wo = SEM_PEND,     \
		.rlock = SEM_DONE,  \
		.wlock = SEM_DONE

/* 通用的 空 Usart结构体 */
#define USART_INIT (Usart){  \
		USART_INIT_VARS,         \
}

#define UART_VALID( n ) (  ((n) >= 0) && ( (n) < NR_UART )  )

/* 通用函数，设定指定的寄存器 */
#if (NR_UART == 1)
#define set_uart_regx( reg, x, no, val )  {\
		reg##0##x = val;
}
#elif (NR_UART == 2)
#define set_uart_regx( reg, x, no, val )  {\
		if( no == 0 ) reg##0##x = val;\
		else reg##1##x = val;\
}
#elif (NR_UART == 3)
#define set_uart_regx( reg, x, no, val )  {\
		if( no == 0 ) reg##0##x = val;\
		else if( no == 1 ) reg##1##x = val;\
		else reg##2##x = val;\
}
#elif (NR_UART == 4)
#define set_uart_regx( reg, x, no, val )  {\
		if( no == 0 ) reg##0##x = val;\
		else if( no == 1 ) reg##1##x = val;\
		else if( no == 2 ) reg##2##x = val;\
		else reg##3##x = val;\
}
#endif

/* 通用函数，设定指定的寄存器 */
#if (NR_UART == 1)
#define set_uart_reg( reg, no, val )  {\
		reg##0 = val;
}
#elif (NR_UART == 2)
#define set_uart_reg( reg, no, val )  {\
		if( no == 0 ) reg##0 = val;\
		else reg##1 = val;\
}
#elif (NR_UART == 3)
#define set_uart_reg( reg, no, val )  {\
		if( no == 0 ) reg##0 = val;\
		else if( no == 1 ) reg##1 = val;\
		else reg##2 = val;\
}
#elif (NR_UART == 4)
#define set_uart_reg( reg, no, val )  {\
		if( no == 0 ) reg##0 = val;\
		else if( no == 1 ) reg##1 = val;\
		else if( no == 2 ) reg##2 = val;\
		else reg##3 = val;\
}
#endif

/* 通用函数，获取指定的寄存器 */
#if (NR_UART == 1)
#define get_uart_regx( reg, x, no, val )  {\
		val = reg##0##x;
}
#elif (NR_UART == 2)
#define get_uart_regx( reg, x, no, val )  {\
		if( no == 0 ) val = reg##0##x;\
		else val = reg##1##x;\
}
#elif (NR_UART == 3)
#define get_uart_regx( reg, x, no, val )  {\
		if( no == 0 ) val = reg##0##x;\
		else if( no == 1 ) val = reg##1##x;\
		else val = reg##2##x;\
}
#elif (NR_UART == 4)
#define get_uart_regx( reg, x, no, val )  {\
		if( no == 0 ) val = reg##0##x;\
		else if( no == 1 ) val = reg##1##x;\
		else if( no == 2 ) val = reg##2##x;\
		else val = reg##3##x;\
}
#endif

/* 通用函数，获取指定的寄存器 */
#if (NR_UART == 1)
#define get_uart_reg( reg, no, val )  {\
		val = reg##0;
}
#elif (NR_UART == 2)
#define get_uart_reg( reg, no, val )  {\
		if( no == 0 ) val = reg##0;\
		else val = reg##1;\
}
#elif (NR_UART == 3)
#define get_uart_reg( reg, no, val )  {\
		if( no == 0 ) val = reg##0;\
		else if( no == 1 ) val = reg##1;\
		else val = reg##2;\
}
#elif (NR_UART == 4)
#define get_uart_reg( reg, no, val )  {\
		if( no == 0 ) val = reg##0;\
		else if( no == 1 ) val = reg##1;\
		else if( no == 2 ) val = reg##2;\
		else val = reg##3;\
}
#endif

/* 初始化寄存器 */
#define INIT_REGS( no ) {\
		UBRR##no##H = (uint8_t)(ubrr>>8); \
		UBRR##no##L = (uint8_t)ubrr; \
		UCSR##no##A = 0x00; \
		UCSR##no##B = _BV(TXEN) | _BV(TXCIE); \
		UCSR##no##C = 0x06; \
}

static Uart _u[NR_UART];

/* 初始化串口相关的寄存器，设置波特率，默认8位数据位，1位停止位 */
void uart_init( uint8_t no, UsartBaud ubrr, void *mem, uint8_t sz )
{
	if( !UART_VALID( no ) )
		return;
	pUart u = &_u[no];
	u->status = 0;
	u->wbuf = NULL;
	u->wcnt = 0;
	u->rbuf = rbuf_create( mem, sz );
	reset_mutex( &u->wo );
	reset_mutex( &u->ro );
	set_mutex( &u->rlock );
	set_mutex( &u->wlock );
	cli();
	/*Device Init*/
#if (NR_UART > 0)
	if( no == 0 ){
		INIT_REGS( 0 );
	}
#if (NR_UART > 1)
	else if( no == 1 ){
		INIT_REGS( 1 );
	}
#if (NR_UART > 2)
	else if( no == 2 ){
		INIT_REGS( 2 );
	}
#if (NR_UART > 3)
	else if( no == 3 ){
		INIT_REGS( 3 );
	}
#endif /* end the number judgement */
#endif
#endif
#endif
	sei();
}

/* 设置波特率 */
int uart_set_baud( uint8_t no, UsartBaud ubrr )
{
	if( !UART_VALID( no ) )
		return ERR_DEV_NOT_FOUND;
	cli();
	set_uart_regx( UBRR, L, no, ubrr & 0x00ff );
	set_uart_regx( UBRR, H, no, ubrr >> 8 );
	sei();
	return 0;
}

/* 设置校验证位 */
int uart_set_checkbit( uint8_t no, enum CheckBitType ct )
{
	if( !UART_VALID( no ) )
		return ERR_DEV_NOT_FOUND;
	uint8_t cbs = ct;
	uint8_t ucsrc;
	get_uart_regx( UCSR, C, no, ucsrc );
	if( cbs != 0x03 )
		ucsrc &= ~ ( _BV( UPM0 ) | _BV(UPM1) );
	ucsrc |= cbs;
	set_uart_regx( UCSR, C, no, ucsrc );
	return 0;
}

/* 设置停止位 */
int uart_set_stopbits( uint8_t no, uint8_t stb )
{
	if( !UART_VALID( no ) )
		return ERR_DEV_NOT_FOUND;
	uint8_t ucsrc;
	get_uart_regx( UCSR, C, no, ucsrc );
	if(stb > 1){
		clr_bit( ucsrc, USBS );
	}else{
		set_bit( ucsrc, USBS );
	}
	set_uart_regx( UCSR, C, no, ucsrc );
	return 0;
}

/* 打开串口 */
int uart_open( uint8_t no, UartMode mode )
{
	if( ! UART_VALID(no) )
		return ERR_DEV_NOT_FOUND;
	/* 打开读功能 */
	if( bit_test( mode, UART_R ) ){
		if( bit_test( _u[no].status, UART_R ) ){
			return ERR_DEV_CONFLICT;
		}else{
			uint8_t reg;
			cli();
			get_uart_regx( UCSR, B, no, reg );
			reg |= _BV( RXCIE ) | _BV( RXEN );
			set_uart_regx( UCSR, B, no, reg );
			set_bit( _u[no].status, UART_R );
			sei();
		}
	}
	/* 打开写功能，由于在uart_init之后，串口已经随时可写，所以不做任何事情 */
	if( bit_test( mode, UART_W ) ){

	}
	return 0;
}
/* 关闭指定功能 */
int uart_close( uint8_t no, UartMode mode )
{
	if( bit_test( mode, UART_R ) ){
		uint8_t reg;
		cli();
		get_uart_regx( UCSR, B, no, reg );
		reg &= ~( _BV(RXCIE) | _BV(RXEN) );
		set_uart_regx( UCSR, B, no, reg );
		clr_bit( _u[no].status, UART_R );
		sei();
		rbuf_clear( _u[no].rbuf );
	}
	return 0;
}

/* 发送中断处理器
 * 如果还有数据要发送(wcnt > 0)，发送下一个数据，计数器减少
 * 如果当前已经没有数据要传送了，停止，并释放wo(write over)信号，同时禁止RX中断 */
void uart_txi_handler( uint8_t no )
{
	if( !UART_VALID( no ) )
		return;
	pUart u = &_u[no];
	if( bit_test( u->status, UART_W ) ){
		if( u->wcnt > 0 ){
			set_uart_reg( UDR, no, *(u->wbuf) );
			++ (u->wbuf);
			-- (u->wcnt);
		}else{
			u->wbuf = NULL;
			set_mutex_int( &u->wo );
		}
	}
}

/* 发送指定字节数的数据
 * 三个参数是串口号，数据所在地，数据长度
 * 返回是实际写入的数据数 */
int uart_write( uint8_t no, const void *buf, size_t cnt )
{
	if( !UART_VALID(no) )
		return -1;
	if( cnt <= 0 )
		return 0;
	pUart u = &_u[no];
	wait_mutex( &u->wlock );

	u->wbuf = ( (char *)buf );
	u->wcnt = cnt - 1;
	set_bit( u->status, UART_W );
	set_uart_reg( UDR, no, *( u->wbuf ++ ) );
	wait_mutex( &u->wo );
	clr_bit( u->status, UART_W );

	set_mutex( &u->wlock );
	return ( cnt - u->wcnt );
}

/* 接收中断处理器
 * 将数据放入接收缓冲区中。如果缓冲区是空的，那么就设置信号量ro，表示有新的数据进入了缓冲区
 */
void uart_rxi_handler( uint8_t no )
{
	if( !UART_VALID(no) )
		return;
	uint8_t data;
	get_uart_reg( UDR, no, data );
	Rbuf *rb = _u[no].rbuf;
	if( rbuf_empty( rb ) ){
		set_mutex_int( &_u[no].ro );
	}
	rbuf_push( rb, data );
}

/* 读取指定字节数的数据 */
int uart_read( uint8_t no, void *buf, size_t cnt )
{
	if( !UART_VALID(no) )
		return -1;
	if( cnt <= 0 )
		return 0;
	pUart u = &_u[no];
	if( !test_bit( u->status, UART_R) )
		return ERR_NOT_OPEN;

	wait_mutex( &u->rlock );
	size_t i;
	for( i = 0; i < cnt; ++i ){
		if( rbuf_empty( u->rbuf ) ){
			wait_mutex( &u->ro );
			if( bit_test( u->status, UART_RBRK ) ){
				clr_bit( u->status, UART_RBRK );
				return i;
			}
		}
		((uint8_t*)buf)[i] = rbuf_pop_front( u->rbuf );
	}

	set_mutex( &u->rlock );

	return i;
}

/* 给usartRead操作设一个时限，超时会结束read操作 */
void uart_set_timeout( uint8_t no, unsigned int timeout )
{

}
/* 打断当前的读进程 */
void uart_read_break( uint8_t no )
{
	if( ! UART_VALID(no) )
		return;
	set_bit( _u[no].status, UART_RBRK );
	set_mutex( &_u[no].ro );
}

